home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / TIPMAIL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  11.4 KB  |  461 lines

  1. /* "Dumb terminal" mailbox interface
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  *    May '91 Bill Simpson
  5.  *        move to separate file for compilation & linking
  6.  *    Sep '91 Bill Simpson
  7.  *        minor changes for DTR & RLSD
  8.  *      Jan '93 Doug Crompton
  9.  *              Mods to code to make it work with both terminal
  10.  *              and Modem. Timers and CD check revamped. Now Always
  11.  *              detects CD loss and timeouts work properly.
  12.  *              Setting Tiptimeout to 0 disables idle and CD loss check
  13.  *
  14.  *              Command Syntax now : 'start tip <interface> <modem|terminal>'
  15.  */
  16. #include "global.h"
  17. #include "commands.h"
  18. #include "mbuf.h"
  19. #include "timer.h"
  20. #include "proc.h"
  21. #include "iface.h"
  22. #ifdef UNIX
  23. #include "unixasy.h"
  24. #else
  25. #include "n8250.h"
  26. #endif
  27. #include "asy.h"
  28. #include "usock.h"
  29. #include "telnet.h"
  30. #include "mailbox.h"
  31. #include "devparam.h"
  32.  
  33. #if !defined(_lint)
  34. static char rcsid[] OPTIONAL = "$Id: tipmail.c,v 1.24 1997/08/19 01:19:22 root Exp root $";
  35. #endif
  36.  
  37. #if defined(TIPMAIL) || defined(ALLSERV)
  38.  
  39. static struct tipcb *Tiplist;
  40. struct suspended *Tipsuspended;
  41.  
  42. static void tip_in (int dev, void *n1, void *n2);
  43. static void tipidle (void *t);
  44. void suspendTipMail (struct mbx * m);
  45.  
  46. unsigned Tiptimeout = 180;    /* Default tip inactivity timeout (seconds) */
  47.  
  48.  
  49. /* Input process */
  50. static void
  51. tip_in (int dev, void *n1, void *n2 OPTIONAL)
  52. {
  53. struct tipcb *tip;
  54. struct mbuf *bp;
  55. const char *buf[2];
  56. char line[MBXLINE];
  57. int c, ret, pos = 0;
  58.  
  59.     line[0] = 0;
  60.     tip = (struct tipcb *) n1;
  61.     while ((c = get_asy (dev)) != -1) {
  62.         tip->firstwarn = 1;
  63.         tip->timeout = tip->default_timeout;
  64.         Asy[dev].iface->lastrecv = secclock ();
  65.  
  66.         if (!tip->raw) {
  67.             c &= 0x7f;
  68.             ret = 0;
  69.             if (tip->echo == WONT) {
  70.                 switch (c) {
  71.                     case 18:    /* CTRL-R */
  72.                         bp = pushdown (qdata ((unsigned char *) line, (int16) pos), 4);
  73. #ifndef TNOS_68K
  74.                         memcpy (bp->data, "^R\r\n", 4);
  75. #else
  76.                         memcpy (bp->data, "^R\r\l", 4);
  77. #endif
  78.                         ret = 1;
  79.                         break;
  80.                     case 0x7f:    /* DEL */
  81.                     case '\b':
  82.                         bp = NULLBUF;
  83.                         if (pos) {
  84.                             --pos;
  85.                             bp = qdata ((const unsigned char *) "\b \b", 3);
  86.                         }
  87.                         ret = 1;
  88.                         break;
  89. #ifndef TNOS_68K
  90.                     case '\r':
  91. #else
  92.                     case '\l':
  93. #endif
  94.                         c = '\n';    /* CR => NL */
  95.                     case '\n':
  96. #ifndef TNOS_68K
  97.                         bp = qdata ((const unsigned char *) "\r\n", 2);
  98. #else
  99.                         bp = qdata ("\r\l", 2);
  100. #endif
  101.                         break;
  102.                     default:
  103.                         bp = pushdown (NULLBUF, 1);
  104.                         *bp->data = uchar (c);
  105.                         break;
  106.                 }
  107.                 (void) asy_send (dev, bp);
  108.                 tip->iface->lastsent = secclock ();
  109.                 if (ret)
  110.                     continue;
  111.             }
  112.             line[pos++] = (char) c;
  113.             if (pos == MBXLINE - 1 || tip->echo == WILL || c == '\n') {
  114.                 line[pos] = '\0';
  115.                 pos = 0;
  116.                 usputs (tip->s, line);
  117.                 usflush (tip->s);
  118.             }
  119.         } else {
  120.             usputc (tip->s, uchar (c));
  121.             usflush (tip->s);
  122.         }
  123.     }
  124.     /* get_asy() failed, terminate */
  125.     close_s (tip->s);
  126.     tip->in = tip->proc;
  127.     tip->proc = Curproc;
  128.     buf[1] = Asy[dev].iface->name;
  129.     (void) tip0 (2, buf, NULL);
  130. }
  131.  
  132.  
  133.  
  134. /* Start mailbox on serial line */
  135. int
  136. tipstart (int argc, char *argv[], void *p)
  137. {
  138. register struct iface *ifp;
  139. register struct asy *ap;
  140. register struct tipcb *tip;
  141. struct mbuf *bp, *dp, *op;    /* op is output, dp is duplicate */
  142. char const *buf[2];
  143. int dev, c, i, off, cnt, cmd, s[2], type = TIP;
  144. #ifndef UNIX
  145. struct fifo *fp;
  146. #endif
  147.  
  148.     if ((ifp = if_lookup (argv[1])) == NULLIF) {
  149.         tprintf (Badinterface, argv[1]);
  150.         return 1;
  151.     }
  152.     for (dev = 0, ap = Asy; dev < ASY_MAX; dev++, ap++)
  153.         if (ap->iface == ifp)
  154.             break;
  155.     if (dev == ASY_MAX) {
  156.         tprintf ("Interface %s not asy port\n", argv[1]);
  157.         return 1;
  158.     }
  159.     if (ifp->raw == bitbucket) {
  160.         tprintf ("Tip session already active on %s\n", argv[1]);
  161.         return 1;
  162.     }
  163.     ksignal (Curproc, 0);    /* Don't keep the parser waiting */
  164.     chname (Curproc, "PBBS tip");
  165.     tip = (struct tipcb *) callocw (1, sizeof (struct tipcb));
  166.  
  167.     if (argc > 2 && *argv[2] == 'm')
  168.         tip->modem = 1;
  169.     tprintf ("Tip started on %s -  with%s CD check - ", argv[1], (tip->modem) ? "" : "out");
  170.     tip->default_timeout = (argc > 3) ? (unsigned) atoi (argv[3]) : Tiptimeout;
  171.     if (tip->default_timeout)
  172.         tprintf ("%d Second", tip->default_timeout);
  173.     else
  174.         tputs ("No");
  175.     tputs (" Timeout\n");
  176.  
  177.  
  178.     /* Save output handler and temporarily redirect output to null */
  179.     tip->asy_dev = dev;
  180.     tip->rawsave = ifp->raw;
  181.     ifp->raw = bitbucket;
  182.     tip->iface = ifp;
  183.     tip->proc = Curproc;
  184.     tip->timer.func = tipidle;
  185.     tip->timer.arg = (void *) tip;
  186.     tip->raw = 0;
  187.     tip->next = Tiplist;
  188.     Tiplist = tip;
  189.     buf[1] = ifp->name;
  190.  
  191.     /* Suspend packet input drivers */
  192.     suspend (ifp->rxproc);
  193.  
  194.     for (;;) {
  195.         (void) ifp->ioctl (ifp, PARAM_UP, TRUE, 0L);
  196.         /* Wait for DCD to be asserted if modem */
  197.         if (tip->modem) {
  198.             kpause (1000);
  199. #ifndef MSDOS
  200.             while (!carrier_detect (tip->asy_dev))
  201.                 kwait (NULL);
  202.             kpause (1000L);
  203. #endif
  204.         }
  205.         if (socketpair (AF_LOCAL, SOCK_STREAM, 0, s) == -1) {
  206.             tprintf ("Could not create socket pair, errno %d\n", errno);
  207.             (void) tip0 (2, buf, p);
  208.             return 1;
  209.         }
  210.         (void) seteol (s[0], "\n");
  211.         (void) seteol (s[1], "\n");
  212.         tip->echo = WONT;
  213.         tip->s = s[0];
  214.         if (tip->modem)
  215.             log (tip->s, "Phone Mailbox Login");
  216.         (void) newproc ("pbbs_incom", 2048, pbbs_incom, s[1], (void *) type, (void *) tip, 0);
  217.  
  218.         /* check for line idle timeout and CD failure */
  219.         tip->firstwarn = 1;
  220.         tip->timeout = tip->default_timeout;
  221.         set_timer (&tip->timer, 1000L);
  222.         start_timer (&tip->timer);
  223.  
  224.         (void) setflush (tip->s, -1);
  225.         (void) sockmode (tip->s, SOCK_ASCII);
  226.  
  227.         /* Now fork into two paths, one rx, one tx */
  228. #ifndef UNIX
  229.         /* first clear (ignore) junk in asyinc input
  230.            which is always receiving - modem can garbage
  231.            on disconnect
  232.         */
  233.         fp = &ap->fifo;
  234.         fp->wp = fp->rp = fp->buf;
  235.         fp->cnt = 0;
  236. #endif
  237.  
  238.         tip->in = newproc ("PBBS tip in", 256, tip_in, dev, (void *) tip, NULL, 0);
  239.         while ((cnt = recv_mbuf (tip->s, &bp, 0, NULL, 0)) != -1) {
  240.             if (!tip->raw) {
  241.                 (void) dup_p (&dp, bp, off = 0, (int16) cnt);    /* dup the whole pkt to pull */
  242.                 for (i = 0; i < cnt; i++)
  243.                     switch (PULLCHAR (&dp)) {    /*lint !e506 */
  244.                         case IAC:    /* ignore most telnet options */
  245.                             (void) dup_p (&op, bp, (int16) off, (int16) (i - off));
  246.                             (void) asy_send (dev, op);
  247.                             ifp->lastsent = secclock ();
  248.  
  249.                             if ((cmd = ++i < cnt ? PULLCHAR (&dp) : recvchar (tip->s)) == EOF)    /*lint !e506 */
  250.                                 break;
  251.                             if (cmd > 250 && cmd < 255) {
  252.                                 if ((c = ++i < cnt ? PULLCHAR (&dp) : recvchar (tip->s)) == EOF)    /*lint !e506 */
  253.                                     break;
  254.                                 switch (cmd) {
  255.                                     case WILL:
  256.                                         if (c == TN_ECHO) {
  257.                                             tip->echo = cmd;
  258.                                             cmd = DO;
  259.                                         } else
  260.                                             cmd = DONT;
  261.                                         break;
  262.                                     case WONT:
  263.                                         if (c == TN_ECHO)
  264.                                             tip->echo = cmd;
  265.                                         cmd = DONT;
  266.                                         break;
  267.                                     case DO:
  268.                                     case DONT:
  269.                                         cmd = WONT;
  270.                                         break;
  271.                                     default:
  272.                                         break;
  273.                                 }
  274.                                 usprintf (tip->s, "%c%c%c", IAC, cmd, c);
  275.                                 usflush (tip->s);
  276.                             }
  277.                             off = i + 1;
  278.                             break;
  279.                         case '\r':
  280.                             if (++i < cnt &&    /* Skip NL but not IAC */
  281.                                 (PULLCHAR (&dp) == IAC)) {        /*lint !e506 */
  282.                                 dp = pushdown (dp, 1);
  283.                                 *dp->data = IAC;
  284.                             }
  285.                             break;
  286. #ifndef TNOS_68K
  287.                         case '\n':
  288. #else
  289.                         case '\l':
  290. #endif
  291.                             (void) dup_p (&op, bp, (int16) off, (int16)(i - off));
  292. #ifndef TNOS_68K
  293.                             append (&op, qdata ((const unsigned char *) "\r\n", 2));
  294. #else
  295.                             append (&op, qdata ("\r\l", 2));
  296. #endif
  297.                             (void) asy_send (dev, op);
  298.                             ifp->lastsent = secclock ();
  299.                             off = i + 1;
  300.                             break;
  301.                         default:
  302.                             break;
  303.                     }
  304.  
  305.                 (void) pullup (&bp, (unsigned char *) 0, (int16) off);
  306.                 (void) asy_send (dev, bp);
  307.             } else
  308.                 (void) asy_send (dev, bp);
  309.  
  310.             ifp->lastsent = secclock ();
  311.  
  312.             kwait (NULL);
  313.         }
  314.         stop_timer (&tip->timer);
  315.         kpause (2000L);
  316.         close_s (tip->s);
  317.         killproc (tip->in);
  318.         tip->in = NULLPROC;
  319.  
  320.         kwait (itop (s[1]));    /* let mailbox terminate, if necessary */
  321.  
  322.         if (!tip->keep && tip->modem) {
  323.             /* Tell line to go down */
  324.             (void) ifp->ioctl (ifp, PARAM_DOWN, TRUE, 0L);
  325.             kpause (5000);
  326.         }
  327.     }
  328. }
  329.  
  330.  
  331.  
  332. int
  333. tip0 (int argc OPTIONAL, char const *argv[], void *p OPTIONAL)
  334. {
  335. register struct iface *ifp;
  336. struct tipcb *tip, *prev = NULLTIP;
  337. struct proc *proc;
  338.  
  339.     if ((ifp = if_lookup (argv[1])) == NULLIF) {
  340.         tprintf (Badinterface, argv[1]);
  341.         return 1;
  342.     }
  343.     for (tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
  344.         if (tip->iface == ifp) {
  345.             if (prev != NULLTIP)
  346.                 prev->next = tip->next;
  347.             else
  348.                 Tiplist = tip->next;
  349.             proc = tip->proc;
  350.             close_s (tip->s);
  351.             ifp->raw = tip->rawsave;
  352.             resume (ifp->rxproc);
  353.             stop_timer (&tip->timer);
  354.             killproc (tip->in);
  355.             free ((char *) tip);
  356.             killproc (proc);
  357.             return 0;
  358.         }
  359.     return 0;
  360. }
  361.  
  362.  
  363.  
  364. static void
  365. tipidle (void *t)
  366. {
  367. struct tipcb *tip;
  368. #ifndef TNOS_68K
  369. static const char *msg1 = "Line idle - One minute to disconnect...\007\r\n";
  370. static const char *msg2 = "Disconnecting...\007\r\n";
  371. #else
  372. static const char *msg1 = "Line idle - One minute to disconnect...\007\r\l";
  373. static const char *msg2 = "Disconnecting...\007\r\l";
  374. #endif
  375.  
  376.     tip = (struct tipcb *) t;
  377.  
  378.     if (tip->modem
  379. #ifndef MSDOS
  380.        && !carrier_detect (tip->asy_dev)
  381. #endif
  382.        ) {
  383.         close_s (tip->s);
  384.         return;
  385.     }
  386.     if (tip->default_timeout && (int)(--tip->timeout) <= 0) {
  387.         if (tip->firstwarn) {
  388.             tip->iface->lastsent = secclock ();
  389.             (void) asy_send (tip->iface->dev, qdata ((const unsigned char *) msg1, (int16) strlen (msg1)));
  390.             tip->timeout = 60;
  391.             start_timer (&tip->timer);
  392.             tip->firstwarn = 0;
  393.         } else {
  394.             (void) asy_send (tip->iface->dev, qdata ((const unsigned char *) msg2, (int16) strlen (msg2)));
  395.             close_s (tip->s);
  396.         }
  397.     } else
  398.         start_timer (&tip->timer);
  399. }
  400.  
  401.  
  402.  
  403. void
  404. suspendTipMail (struct mbx *m)
  405. {
  406. char const *args[2];
  407.  
  408.     if (m->tip->modem) {    /* if modem connect, we can resume */
  409.         /* save the interface in the suspended array, for asytimer() */
  410.         Tipsuspended[m->tip->asy_dev].ifp = m->tip->iface;
  411.         Tipsuspended[m->tip->asy_dev].modem = m->tip->modem;
  412.         Tipsuspended[m->tip->asy_dev].timeout = m->tip->default_timeout;
  413.         m->tip->keep = 1;
  414.         tputs ("Tipmail will resume after you disconnect\n");
  415.     } else
  416.         tputs ("Tipmail terminated on this interface\n");
  417.     usflush (Curproc->output);
  418.     /* now stop the tipmail */
  419.     args[1] = m->tip->iface->name;
  420.     (void) tip0 (2, args, NULL);
  421. }
  422. #endif /* ALLSERV || TIPMAIL */
  423.  
  424.  
  425.  
  426. static int Stelnet = -1;
  427.  
  428. /* Start up Telnet server */
  429. int
  430. telnet1 (int argc, char *argv[], void *p OPTIONAL)
  431. {
  432.     return (installserver (argc, argv, &Stelnet, "Telnet listener", IPPORT_TELNET,
  433.         INADDR_ANY, "pbbs", pbbs_incom, 2048, (void *) TELNET_LINK));
  434. }
  435.  
  436. /* Stop telnet server */
  437. int
  438. telnet0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  439. {
  440.     return (deleteserver (&Stelnet));
  441. }
  442.  
  443.  
  444. static int SFBBtelnet = -1;
  445.  
  446. /* Start up FBB Telnet server */
  447. int
  448. fbbtelnet1 (int argc, char *argv[], void *p OPTIONAL)
  449. {
  450.     return (installserver (argc, argv, &SFBBtelnet, "FBB/Telnet listener", IPPORT_FTELNET,
  451.         INADDR_ANY, "pbbs", pbbs_incom, 2048, (void *) (TELNET_LINK | JUMPSTARTED)));
  452. }
  453.  
  454. /* Stop FBB telnet server */
  455. int
  456. fbbtelnet0 (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  457. {
  458.     return (deleteserver (&SFBBtelnet));
  459. }
  460.  
  461.